/********************************************************************************
  * @file    programconfig.h
  * @author  Lun Li
  * @version V2.2.0
  * @date    2022.7.8
  * @brief   This file contains all the functions prototypes for ProgramConfig.
  ******************************************************************************/

#ifndef PROGRAMCONFIG_H
#define PROGRAMCONFIG_H

#include <QDir>
#include <QFile>
#include <QSettings>
#include <QFont>
#include <QColor>

/************
  * ProgramConfig类，代表了程序的配置。
  ***********/
class ProgramConfig : public QSettings
{
    Q_OBJECT
public:
    // iverilog -d debug属性的枚举值及其对应的字符串
    enum DebugFlag {
        scope, eval_tree, elaborate, synth2
    };
    const QStringList debugFlagStr {
        QStringLiteral("scope"), QStringLiteral("eval_tree"),
        QStringLiteral("elaborate"), QStringLiteral("synth2")
    };

    // iverilog -g generation属性的枚举值及其对应的字符串
    enum GenerationFlag {
        IEEE1995, IEEE2001, IEEE2001_noconfig, IEEE2005,
        IEEE2009, IEEE2012, verilog_ams,
        assertions, supported_assertions, no_assertions,
        specify, no_specify,
        std_include, no_std_include,
        xtypes, no_xtypes,
        io_range_error, no_io_range_error,
        strict_ca_eval, no_strict_ca_eval,
        strict_expr_width, no_strict_expr_width,
        shared_loop_index, no_shared_loop_index
    };
    const QStringList generationFlagStr {
        QStringLiteral("1995"), QStringLiteral("2001"),
        QStringLiteral("2001-noconfig"), QStringLiteral("2005"),
        QStringLiteral("2009"), QStringLiteral("2012"),
        QStringLiteral("verilog-ams"), QStringLiteral("assertions"),
        QStringLiteral("supported-assertions"), QStringLiteral("no-assertions"),
        QStringLiteral("specify"), QStringLiteral("no-specify"),
        QStringLiteral("std-include"), QStringLiteral("no-std-include"),
        QStringLiteral("xtypes"), QStringLiteral("no-xtypes"),
        QStringLiteral("io-range-error"), QStringLiteral("no-io-range-error"),
        QStringLiteral("strict-ca-eval"), QStringLiteral("no-strict-ca-eval"),
        QStringLiteral("strict-expr-width"), QStringLiteral("no-strict-expr-width"),
        QStringLiteral("shared-loop-index"), QStringLiteral("no-shared-loop-index"),
    };

    // iverilog -W warning属性的枚举值及其对应的字符串
    enum WarningFlag {
        all,
        anachronisms, no_anachronisms,
        implicit, no_implicit,
        implicit_dimensions, no_implicit_dimensions,
        macro_redefinition, no_macro_redefinition,
        macro_replacement, no_macro_replacement,
        portbind, no_portbind,
        select_range, no_select_range,
        timescale, no_timescale,
        infloop,
        sensitivity_entire_vector, no_sensitivity_entire_vector,
        sensitivity_entire_array, no_sensitivity_entire_array,
        floating_nets, no_floating_nets
    };
    const QStringList warningFlagStr {
        QStringLiteral("all"),
        QStringLiteral("anachronisms"), QStringLiteral("no-anachronisms"),
        QStringLiteral("implicit"), QStringLiteral("no-implicit"),
        QStringLiteral("implicit-dimensions"), QStringLiteral("no-implicit-dimensions"),
        QStringLiteral("macro-redefinition"), QStringLiteral("no-macro-redefinition"),
        QStringLiteral("macro-replacement"), QStringLiteral("no-macro-replacement"),
        QStringLiteral("portbind"), QStringLiteral("no-portbind"),
        QStringLiteral("select-range"), QStringLiteral("no-select-range"),
        QStringLiteral("timescale"), QStringLiteral("no-timescale"),
        QStringLiteral("infloop"),
        QStringLiteral("sensitivity-entire-vector"), QStringLiteral("no-sensitivity-entire-vector"),
        QStringLiteral("sensitivity-entire-array"), QStringLiteral("no-sensitivity-entire-array"),
        QStringLiteral("floating-nets"), QStringLiteral("no-floating-nets")
    };

    // iverilog -T 时序属性的枚举值及其对应的字符串
    enum TimingFlag {
        timing_min, timing_typ, timing_max
    };
    const QStringList timingFlagStr {
        QStringLiteral("min"), QStringLiteral("typ"), QStringLiteral("max")
    };

    explicit ProgramConfig(const QString &fileName, QSettings::Format format, QObject *parent = nullptr);

    // 编辑器的字体
    const QFont &font() const;
    void setFont(const QFont &newFont);

    // 编辑器的制表符宽度
    int tabWidth() const;
    void setTabWidth(int newWidth);

    // 编辑器的关键字颜色
    const QColor &keywordColor() const;
    void setKeywordColor(const QColor &newColor);

    // 编辑器的字符串颜色
    const QColor &quotationColor() const;
    void setQuotationColor(const QColor &newColor);

    // 编辑器的数字颜色
    const QColor &numberColor() const;
    void setNumberColor(const QColor &newColor);

    // 编辑器的注释颜色
    const QColor &commentColor() const;
    void setCommentColor(const QColor &newColor);

    // 编辑器的系统函数颜色
    const QColor &systemFunctionColor() const;
    void setSystemFunctionColor(const QColor &newColor);

    // iverilog的文件夹路径
    const QString &compileToolPath() const;
    void setCompileToolPath(const QString &newPath);

    // gtkwave的文件夹路径
    const QString &waveToolPath() const;
    void setWaveToolPath(const QString &newPath);

    // 是否开启日志输出
    bool isLogEnabled() const;
    void setIsLogEnabled(bool newEnabled);

    // 是否在编译完成后读取模块层次
    bool isLoadHierarchyEnabled() const;
    void setIsLoadHierarchyEnabled(bool newEnabled);

    // iverilog超时时间（单位ms）
    qint32 iverilogTimeout() const;
    void setIverilogTimeout(qint32 newIverilogTimeout);

    // vvp超时时间（单位ms）
    qint32 vvpTimeout() const;
    void setVvpTimeout(qint32 newVvpTimeout);

    // iverilog -c指令，命令文件路径
    const QString &commandFilePath() const;
    void setCommandFilePath(const QString &newPath);

    // iverilog -d指令，debug指令
    const QList<DebugFlag> &debugFlags() const;
    void setdebugFlags(const QList<DebugFlag> &newFlags);

    // iverilog -g指令，generation指令
    const QList<GenerationFlag> &generationFlags() const;
    void setGenerationFlags(const QList<GenerationFlag> &newFlags);

    // iverilog -i指令，是否忽略无法找到的模块
    bool ifIgnoreMissingModule() const;
    void setIfIgnoreMissingModule(bool newIgnore);

    // iverilog -L指令，VPI模块文件夹路径
    const QStringList &VPIModuleDirs() const;
    void setVPIModuleDirs(const QStringList &newDirs);

    // iverilog -I指令，库文件路径
    const QStringList &libraryFilePaths() const;
    void setLibraryFilePaths(const QStringList &newPaths);

    // iverilog -M指令，统计参与编译的文件
    const QStringList &contributionModePaths() const;
    void setContributionModePaths(const QStringList &newModePaths);

    // iverilog -m指令，VPI模块名
    const QStringList &VPIModules() const;
    void setVPIModules(const QStringList &newModules);

    // iverilog -o指令，输出文件名
    const QString &outputFileName() const;
    void setOutputFileName(const QString &newName);

    // iverilog -S指令，是否启动综合
    bool ifActivateSynth() const;
    void setIfActivateSynth(bool newActivate);

    // iverilog -u指令，将源文件视为编译单元
    bool ifTreatAsUnit() const;
    void setIfTreatAsUnit(bool newTreat);

    // iverilog -v指令，是否输出详细信息
    bool ifBeVerbose() const;
    void setIfBeVerbose(bool newVerbose);

    // iverilog -V指令，只输出版本信息
    bool ifPrintVersion() const;
    void setIfPrintVersion(bool newPrint);

    // iverilog -W指令，输出警告信息
    const QList<WarningFlag> &warningFlags() const;
    void setWarningFlags(const QList<WarningFlag> &newFlags);

    // iverilog -y指令，库文件夹路径
    const QStringList &libraryDirs() const;
    void setLibraryDirs(const QStringList &newDirs);

    // iverilog -Y指令，指定源文件的后缀
    const QStringList &suffixes() const;
    void setSuffixes(const QStringList &newSuffixes);

    // iverilog -E指令，只执行预编译，指定预编译输出文件名
    const QString &preOutputFileName() const;
    void setPreOutputFileName(const QString &newName);

    // iverilog -D指令，定义宏
    const QStringList &macros() const;
    void setMacros(const QStringList &newMacros);

    // iverilog -P指令，定义参数
    const QStringList &parameters() const;
    void setParameters(const QStringList &newParameters);

    // iverilog -s指令，定义顶层模块
    const QStringList &topModules() const;
    void setTopModules(const QStringList &newTopModules);

    // iverilog -T指令，定义使用的时序
    TimingFlag timingFlag() const;
    void setTimingFlag(TimingFlag newFlag);

    // VVP额外参数
    const QString &vvpExtra() const;
    void setVvpExtra(const QString &newVvpExtra);

    // 用户上一次打开的路径
    const QString &lastOpenPath() const;
    void setLastOpenPath(const QString &newPath);

    // 语言
    qint32 languageIndex() const;
    void setLanguageIndex(qint32 newLanguageIndex);

signals:
    // 程序相关的配置发生了变化
    void generalConfigChanged();

    // 编辑器相关的配置发生了变化
    void editorConfigChanged();

    // 编译工具的配置发生了变化
    void toolConfigChanged();

    // iverilog参数的配置发生了变化
    void iverilogConfigChanged();

private:
    // 编辑器相关的配置
    QFont m_font;
    int m_tabWidth;    
    QColor m_keywordColor;
    QColor m_quotationColor;
    QColor m_numberColor;
    QColor m_commentColor;
    QColor m_systemFunctionColor;

    // 编译工具相关的配置
    QString m_compileToolPath;
    QString m_waveToolPath;
    bool m_isLogEnabled;
    bool m_isLoadHierarchyEnabled;
    qint32 m_iverilogTimeout;
    qint32 m_vvpTimeout;

    // iverilog参数的配置
    QString m_commandFilePath;
    QList<DebugFlag> m_debugFlags;
    QList<GenerationFlag> m_generationFlags;
    bool m_ifIgnoreMissingModule;
    QStringList m_VPIModuleDirs;
    QStringList m_libraryFilePaths;
    QStringList m_contributionModePaths;
    QStringList m_VPIModules;
    QString m_outputFileName;
    bool m_ifActivateSynth;
    bool m_ifTreatAsUnit;
    bool m_ifBeVerbose;
    bool m_ifPrintVersion;
    QList<WarningFlag> m_warningFlags;
    QStringList m_libraryDirs;
    QStringList m_suffixes;
    QString m_preOutputFileName;
    QStringList m_macros;
    QStringList m_parameters;
    QStringList m_topModules;
    TimingFlag m_timingFlag;
    QString m_vvpExtra;

    // 程序相关的配置
    QString m_lastOpenPath;
    qint32 m_languageIndex;
};

#endif // PROGRAMCONFIG_H
